﻿using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;

namespace Common
{
    /// <summary>
    /// Ftp操作帮助类
    /// </summary>
    public class FtpHelper
    {

        #region 上传
        /// <summary>
        /// FTP的服务器地址，格式为ftp://192.168.1.234:8021/。
        /// </summary>
        private string FtpUrl { get; set; }
        /// <summary>
        /// //FTP服务器的用户名
        /// </summary>
        private string FtpUserName { get; set; }
        /// <summary>
        /// //FTP服务器的密码
        /// </summary>
        private string FtpPassword { get; set; }
        /// <summary>
        /// 远程上传目录
        /// </summary>
        private string FtpRemoteUploadDir { get; set; }
        public FtpHelper(string ftpIp, string ftpUserName, string ftpPassword, string ftpPort = "21", string ftpRemoteUploadDir = "Root")
        {
            FtpUrl = string.Format("{0}://{1}:{2}", "ftp", ftpIp, ftpPort);
            FtpUserName = ftpUserName;
            FtpPassword = ftpPassword;
            FtpRemoteUploadDir = ftpRemoteUploadDir;
        }

        /// <summary>
        /// 上传文件到远程ftp
        /// </summary>
        /// <param name="path">本地的文件目录</param>
        /// <param name="name">文件名称</param>
        /// <returns></returns>
        public void UploadFile(string localFilePath)
        {
            FileInfo localfileFileInfo = new FileInfo(localFilePath);
            string remoteFilePath = "";

            //远程文件路径
            if (!string.IsNullOrEmpty(FtpRemoteUploadDir))
            {
                remoteFilePath = $"{FtpUrl}/{FtpRemoteUploadDir}/{localfileFileInfo.Name}";
            }
            else
            {
                remoteFilePath = $"{FtpUrl}/{localfileFileInfo.Name}";
            }
            FtpWebRequest reqFtp = (FtpWebRequest)FtpWebRequest.Create(new Uri(remoteFilePath));
            reqFtp.Method = WebRequestMethods.Ftp.UploadFile;
            reqFtp.UsePassive = false;//只需要添加这一句话
            reqFtp.UseBinary = true;
            reqFtp.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
            reqFtp.KeepAlive = false;
            reqFtp.Proxy = new WebProxy(); //-----The requested FTP command is not supported when using HTTP proxy.
            reqFtp.ContentLength = localfileFileInfo.Length;
            int buffLength = 2048;
            byte[] buff = new byte[buffLength];
            int contentLen;
            using (FileStream fs = localfileFileInfo.OpenRead())
            {
                using (Stream st = reqFtp.GetRequestStream())
                {
                    contentLen = fs.Read(buff, 0, buffLength);
                    while (contentLen != 0)
                    {
                        st.Write(buff, 0, contentLen);
                        contentLen = fs.Read(buff, 0, buffLength);
                    }
                }
            }
        }
        #endregion






        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="ftpPath"></param>
        /// <param name="storagePath"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public static bool Download(string ftpPath, string storagePath, string username, string password)
        {
            bool result = false;
            bool fileIsAvailable = false;

            LogHelper.Debug("开始下载Ftp：\r\n" + ftpPath);
            for (int i = 0; i < 3; i++)
            {
                if (!FileIsAvailable(ftpPath, username, password))
                {
                    Thread.Sleep(1000);
                }
                else
                {
                    fileIsAvailable = true;
                    break;
                }
            }
            if (fileIsAvailable)
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpPath);

                request.Method = WebRequestMethods.Ftp.DownloadFile;
                request.Credentials = new NetworkCredential(username, password);
                using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
                {
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        using (FileStream fs = new FileStream(storagePath, FileMode.Create))
                        {
                            byte[] buffer = new byte[102400];
                            int read = 0;
                            do
                            {
                                read = responseStream.Read(buffer, 0, buffer.Length);
                                fs.Write(buffer, 0, read);
                                fs.Flush();
                            } while (!(read == 0));
                            fs.Flush();
                            fs.Close();
                            result = true;
                        }
                    }
                }
            }
            else
            {
                LogHelper.Debug("文件最终未找到，或被占用\r\n" + ftpPath);
            }
            LogHelper.Debug("下载Ftp的结果：\r\n" + result + "\r\n" + ftpPath);

            return result;
        }

        /// <summary>
        ///删除文件
        /// </summary>
        /// <param name="ftpPath"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static bool DeleteFile(string ftpPath, string username, string password)
        {
            bool result = false;

            LogHelper.Debug("开始删除Ftp：\r\n" + ftpPath);
            if (FileIsAvailable(ftpPath, username, password))
            {
                FtpWebRequest reqFtp = (FtpWebRequest)FtpWebRequest.Create(ftpPath);

                reqFtp.Method = WebRequestMethods.Ftp.DeleteFile;
                reqFtp.Credentials = new NetworkCredential(username, password);
                using (FtpWebResponse response = (FtpWebResponse)reqFtp.GetResponse())
                {
                    result = true;
                }
            }
            else
            {
                result = true;
            }
            LogHelper.Debug("删除Ftp的结果：\r\n" + result + "\r\n" + ftpPath);

            return result;
        }

        /// <summary>
        /// 文件是否可用
        /// </summary>
        /// <param name="ftpPath"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="searchCount"></param>
        /// <returns></returns>
        public static bool FileIsAvailable(string ftpPath, string username, string password)
        {
            bool result = false;
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpPath);

            request.Credentials = new NetworkCredential(username, password);
            request.Method = WebRequestMethods.Ftp.GetFileSize;
            try
            {
                using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
                {
                    result = true;
                    LogHelper.Debug("文件已经找到，且可用：\r\n" + ftpPath);
                }
            }
            catch (WebException ex)
            {
                using (FtpWebResponse response = (FtpWebResponse)ex.Response)
                {
                    if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable || response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailableOrBusy)
                    {
                        LogHelper.Debug("文件未找到，或被占用：\r\n" + ftpPath);
                    }
                    else
                    {
                        LogHelper.Debug("文件未找到，或被占用：\r\n" + ftpPath + "\r\n报错：" + ex);
                    }
                }
            }

            return result;
        }

        /// <summary>
        ///  文件是否可用（未测试，有问题）
        /// </summary>
        /// <param name="ftpPath"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="searchCount"></param>
        /// <returns></returns>
        public static bool FileIsAvailable2(string ftpPath, string username, string password)
        {
            bool result = false;
            FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(ftpPath);

            reqFTP.Credentials = new NetworkCredential(username, password);
            reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
            using (FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse())
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default))
                {
                    string line = reader.ReadLine();
                    if (line == null)
                    {
                        LogHelper.Debug("文件未找到，或被占用：\r\n" + ftpPath);
                    }
                    else
                    {
                        LogHelper.Debug("文件已经找到，且可用：\r\n" + ftpPath);
                        result = true;
                    }
                }
            }

            return result;
        }

    }


}